﻿using System;
using System.Text;

namespace StartReading.Security.Validation
{
    public class AliasValidation : IValidation<String>
    {        
        private const string AliasPattern = @"^(([A-Za-z0-9]+([._ ]{0,1})[A-Za-z0-9])+)$";
        private const int MinimumAliasLength = 3;
        private const int MaximumAliasLength = 20;

        private AliasValidation()
        {
            this.EmptyStringValidator = EmptyStringValidation.Instance;
            this.RegexValidator = RegexValidation.Instance;
            this.MinimumLengthValidator = MinimumStringLengthValidation.Instance;
            this.MaximumLengthValidator = MaximumStringLengthValidation.Instance;
        }

        #region Lazy Singleton and Thread-Safe
        private static class AliasValidationHolder
        {
            static AliasValidationHolder()
            {
            }

            internal static readonly AliasValidation AliasValidation = new AliasValidation();
        }

        /// <summary>
        /// Gets an instance of AliasValidation class
        /// </summary>
        public static AliasValidation Instance
        {
            get
            {                
                return AliasValidationHolder.AliasValidation;
            }
        }
        #endregion

        private IValidation<String, String> EmptyStringValidator { get; set; }
        private IValidation<String, String, String> RegexValidator { get; set; }
        private IValidation<String, int, String> MinimumLengthValidator { get; set; }
        private IValidation<String, int, String> MaximumLengthValidator { get; set; }

        /// <summary>
        ///     Validates an alias.
        ///     Only alphabetical letters [A-Z, a-z], dot [.], underscore [_] and space [ ] are accepted.
        ///     Alias has to be started and ended with either Alphabetical letters or Numbers.
        ///     Throws ArgumentException if alias is invalid.
        /// </summary>
        /// <param name="alias">An alias to be validated</param>
        public void IsValid( string alias )
        {
            this.EmptyStringValidator.IsValid( alias, "Alias" );
            this.RegexValidator.IsValid( alias, AliasValidation.AliasPattern, String.Format("{0} {1}", 
                "Only alphabetical letters [A-Z, a-z], dot [.], underscore [_] and space [ ] are accepted.",
                "Alias has to be started and ended with either Alphabetical letters or Numbers.") );
            this.MinimumLengthValidator.IsValid( alias, MinimumAliasLength, "Alias" );
            this.MaximumLengthValidator.IsValid( alias, MaximumAliasLength, "Alias" );
        }
    }
}
